package de.tub.bazinga.eventbus;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class DefaultEventBus implements IEventBus {

	private static DefaultEventBus instance;
	private final List<IEventHandler<? extends IEvent>> handler;

	private DefaultEventBus() {
		handler = new ArrayList<IEventHandler<? extends IEvent>>();
	}

	public static synchronized DefaultEventBus getInstance() {
		if (instance == null) {
			instance = new DefaultEventBus();
		}
		return instance;
	}

	@Override
	public void addHandler(IEventHandler<? extends IEvent> handler) {
		this.handler.add(handler);
	}

	@Override
	public void removeHandler(IEventHandler<? extends IEvent> handler) {
		this.handler.remove(handler);
	}

	@Override
	public void fireEvent(IEvent event) {

		for (IEventHandler<? extends IEvent> h : handler) {

			Method handleMethod = getHandleMethod(h, event);

			try {
				handleMethod.invoke(h, event);
			} catch (Exception e) {
				// throw new RuntimeException("This should not happen", e);
			}

		}

	}

	private Method getHandleMethod(IEventHandler<? extends IEvent> h,
			IEvent event) {
		Method returnMethod = null;

		for (Method m : h.getClass().getMethods()) {
			if (m.getName().equals("handleEvent")) {
				if (m.getParameterTypes().length == 1) {
					Class<?> parameterClass = m.getParameterTypes()[0];
					if (parameterClass.isInstance(event)

					) {
						returnMethod = m;
						break;
					}
				}
			}
		}
		return returnMethod;
	}

	@Override
	public void removeAllHandler() {
		handler.clear();
	}

}
